#include <gtest/gtest.h>
#include <thread>
#include "UdpSocketWrapper.hpp"
#include "ParserPacket.hpp"
#include "RtpPacket.hpp"

#include <arpa/inet.h>
#include <string>
#include "common/HiCommonLog.hpp"
#include <functional>
using namespace Hi;
using namespace std;

//bool readRTP(const char* file, void(*OnRead)(const uint8_t*, size_t));
bool readRTP(const char* file, const std::function<void(const uint8_t*, size_t)>& OnRead);
string Byte2Hex(const uint8_t* bArray, size_t bArray_len);

static const char* myIp = "127.0.0.1";

class MyGuardProxy {
public:
	MyGuardProxy() {
		hi_is_ignore_debug(true);
	}
};
static MyGuardProxy proxy;

static void SendUDP() {
    system("ffmpeg -v info -re  -stream_loop -1 -probesize 409600 -fpsprobesize 1  -fflags nobuffer -i rtmp://58.200.131.2:1935/livetv/gxtv  -y -c:v copy  -bsf:v h264_mp4toannexb,dump_extra -map 0:v:0  -f  tee [select=v:f=rtp:ssrc=24591037:payload_type=100]rtp://127.0.0.1:60001");
}

static int packetIndex = 0;

static FILE* f = nullptr;
static const char* filePath = "pcket_100.text";


static void ReceiveMsg(const uint8_t* data, size_t len, 
    const struct sockaddr* addr, UdpSocketWrapper* wrapper) {
	HI_FUNC_DEBUG();
    if (nullptr == f && packetIndex == 0) {
        f = fopen(filePath, "w+");
    }

    //printf("receive rtp message,lien:%d\n", (int)len);
    RtpPacket* packet = hi_RtpPacket_parse(data, len);
    if (packet != nullptr) {
        if (f != nullptr) {
			const char* msg = "\nnot null\n";
            fwrite(msg, sizeof(char), strlen(msg), f);
        }
        delete packet;
    } else {
        if (f != nullptr) {   
			const char* msg = "\nnull\n";         
            fwrite(msg, sizeof(char), strlen(msg), f);
        }
    }    
    if (f != nullptr) {
        string info = Byte2Hex(data, len);
        fwrite("\n[", sizeof(char), strlen("\n["), f);
        fwrite(info.c_str(), sizeof(char), info.size(), f);
        fwrite("]\n", sizeof(char),  strlen("]\n"), f);
    }
    packetIndex++;

    //ASSERT_NE(packet, nullptr);
    if (packetIndex != 0 && packetIndex % 20000 == 0 && f != nullptr) {
		HI_DEBUG("fclose begin");
		printf("fclose begin\n");
        fclose(f);
        f = nullptr;
		HI_DEBUG("fclose end");
		printf("fclose end\n");
    }
}

TEST(RTPParser, Byte2Hex) {
	return;
    const uint8_t data[10] = {172, 254, 3, 6, 9, 0, '\0', 7, 8, 156};
    string info = Byte2Hex(data, 10);
    printf("message:%s\n", info.c_str());
}

TEST(RTPParser, byteIsSamllOrBig) { 
	return;
    short s=1;
    if(s == htons(s))cout<<"byte is big"<<endl;
    else cout<<"byte is samll"<<endl;
	
	int a = 0x12345678;
	char b = *((char*)(&a));		// 指针方式其实就是共用体的本质
	if (0x78 == b)
		cout << "little" << endl;
	else if (0x12 == b)
		cout << "big" << endl;
}

TEST(RTPParser, normal) {
	return;
    //std::thread sendThread(SendUDP);
    UdpSocketWrapper* udp = new UdpSocketWrapper();
	int ret = udp->Listen(myIp, 60001, ReceiveMsg);
	EXPECT_EQ(ret, 0);
	sleep(1000000); 
}


TEST(RTPParser, readHead) {
	return;
#if defined(MS_LITTLE_ENDIAN)
	HI_DEBUG("MS_LITTLE_ENDIAN");
#elif defined(MS_BIG_ENDIAN)
	HI_DEBUG("MS_BIG_ENDIAN");
#else
	HI_DEBUG("MS_OTHER");
#endif
	uint8_t head[2] = {160, 194};
	HI_DEBUG("data:A0C2");
	RtpPacket::Header* header = (RtpPacket::Header*)head;
	HI_DEBUG("padding:%d,csrcCount:%d,version:%d,paloadType:%d", 
		header->padding, header->csrcCount, header->version, header->payloadType);
		
	HI_DEBUG("data:9C24");
	head[0] = 0x9C;
	head[1] = 0x24;
	header = (RtpPacket::Header*)head;
	HI_DEBUG("padding:%d,csrcCount:%d,version:%d,paloadType:%d", 
		header->padding, header->csrcCount, header->version, header->payloadType);
}

static void printRTPInfo(const uint8_t* buf, size_t len) {
	uint8_t first = *buf;
	uint8_t second = *(buf + 1);
	uint8_t third = *(buf + 2);
	uint8_t four = *(buf + 3);
	printf("rtp parser failed, len:%ld, first: %x,second: %x,third: %x,four: %x,last int8:%x， last 2 int8:%x\n", 
		len, first, second, third, four, *(buf + (len - 1)), *(buf + (len - 2)));
}

TEST(RTPParser, readRtpFromFile) {
	return;
	int i = 0;
	int successCount = 0;
	auto func =  [&](const uint8_t* buf, size_t len){
		//printf("get bytes, len is 1400\n");
		i++;
		printf("index:%d\n", i);
		RtpPacket* packet = hi_RtpPacket_parse(buf, len);
		if (nullptr == packet) {
			return;
		} else {
			successCount++;
			hi_RtpPacket_release(&packet);
			packet = nullptr;
		}
	};
	bool ret = readRTP(filePath, func);
	ASSERT_EQ(ret, true);
	printf("success count:%d\n", successCount);
}